import React, {useState} from 'react'
import { InboxOutlined } from '@ant-design/icons';
import { Button, message, Upload } from 'antd';
import './index.css'
import SparkMD5 from 'spark-md5'
import { checkFileExist, fileUpload } from '../../api/upload';

const { Dragger } = Upload;
const UploadSerior = () => {
    const [fileList, setFileList] = useState([]);
    const [uploading, setUploading] = useState(false);
    const [limit, setLimit] = useState(0);
    const uploadUrl = 'http://127.0.0.1:2022/upload'
    const props = {
        // 文件字段名
        name: 'file',
        // 批量上传
        multiple: true,
        // 上传地址
        action: uploadUrl,
        // 请求方式
        method: 'POST',
        // 是否携带cookie
        withCredentials: true,
        // 展示上传列表
        showUploadList:true,
        // 文件上传之前触发
        beforeUpload(file, list){
            setFileList(list)
            return false;
        },
        // 文件改变时触发
        onChange(info) {
          const { status } = info.file;
          if (status !== 'uploading') {
            console.log(info.file, info.fileList);
          }
          if (status === 'done') {
            message.success(`${info.file.name} file uploaded successfully.`);
          } else if (status === 'error') {
            message.error(`${info.file.name} file upload failed.`);
          }
        },
        // 当文件被拖入上传区域时执行的回调功能
        onDrop(e) {
          console.log('Dropped files', e.dataTransfer.files);
        },

        // 文件移除时的回调
        onRemove(file) {
            const index = fileList.indexOf(file);
            const newFileList = fileList.slice();
            newFileList.splice(index, 1);
            setFileList(newFileList);
            console.log(file.name + ",被移除了")
        }
    };

    // 计算MD5
    const getMD5 = (file, fileListID) => {
        return new Promise((resove, reject) => {
            // 使用sparkMD5的ArrayBuffer类，读取二进制文件
            const spark = new SparkMD5.ArrayBuffer()
            const fileReader = new FileReader()
            // 异步操作，读完后的结果
            fileReader.onload = (e) => {
                // 把文件开始传入spark
                spark.append(e.target.result)
                // spark计算出MD5后的结果
                const _md5 = spark.end()
                resove(_md5)
                // 下面可以写一些自己需要的业务代码, 例如 fileItem.fileMD5 = _md5
            }
            // fileReader读取二进制文件
            fileReader.readAsArrayBuffer(file)
        })
    }

    const uploadHandle = async () => {
        // 单个切片文件大小为2MB
        const chunkSize = 2097152;
        // 分片的最小值 10M
        const chunkMinSize = 10485760;
        let chunkFlag = false;
        if(fileList && fileList.length > 0) {
            for(let i = 0; i < fileList.length; i++) {
                if(fileList[i].size > chunkMinSize) {
                    chunkFlag = true;
                }
                // 获取文件的总分片数
                const chunkNum = Math.ceil(fileList[i].size / chunkSize)
                // 取两个md5值作为整体文件的唯一标识
                let fileMd5 = ''
                if (chunkNum >= 2) {
                    let startMd5 = await getMD5(fileList[i].slice(0, 1 * chunkSize))
                    let endMd5 = await getMD5(fileList[i].slice((chunkNum-1) * chunkSize, chunkNum * chunkSize))
                    fileMd5 = startMd5 + endMd5;
                } else {
                    fileMd5 = await getMD5(fileList[i])
                }
                // 判断文件是否存在
                const res = await checkFileExist(fileMd5);
                const { code, data, msg } = res;
                if(data) {
                    message.success('文件秒传成功')
                    console.log('文件在服务器已存在,文件上传成功(大文件秒传原理就是不传)')
                    // 跳过这个文件,不传了
                    continue;
                } else {
                    // 文件不存在，准备上传
                    // 需要分片上传
                    if(chunkFlag) {
                        let start = new Date()
                        for(let currentChunk = 0; currentChunk < chunkNum; currentChunk++) {
                            let formData = new FormData();
                            // 分片上传
                            formData.append("chunkFlag", chunkFlag);
                            // 分片总数
                            formData.append("chunks", chunkNum);
                            // 当前分片数
                            formData.append("currentChunk", currentChunk);
                            // 分片大小
                            formData.append("chunkSize", chunkSize);
                            // 文件类型
                            formData.append('type', fileList[i].type)
                            // 文件总大小
                            formData.append("size", fileList[i].size);
                            // 文件名
                            formData.append("name", fileList[i].name);
                            // 整个文件的id值，及md5值
                            formData.append("fileMd5", fileMd5);
                            // 计算当前文件分片的md5值
                            let currentChunkMd5 = await getMD5(fileList[i].slice(currentChunk * chunkSize, (currentChunk + 1) * chunkSize));
                            formData.append("currentChunkMd5", currentChunkMd5);
                            formData.append("file", fileList[i].slice(currentChunk * chunkSize, (currentChunk + 1) * chunkSize));
                            fileUpload(formData).then(res => {
                               console.log(fileList[i].name + ",分片:" + currentChunk + "上传成功")
                            }).catch(err => {
                                
                            })
                        }
                        let end = new Date()
                        console.log(fileList[i].name + "上传完成,耗时:" + (end - start))
                    } else {
                        // 直接传，部分片
                           let formData = new FormData();
                            // 分片上传
                            formData.append("chunkFlag", chunkFlag);
                            // 文件类型
                            formData.append('type', fileList[i].type)
                            // 文件总大小
                            formData.append("size", fileList[i].size);
                            // 文件名
                            formData.append("name", fileList[i].name);
                            // 整个文件的id值，及md5值
                            formData.append("fileMd5", fileMd5);
                            // 计算当前文件分片的md5值
                            formData.append("file", fileList[i]);
                            fileUpload(formData).then(res => {
                                console.log(res)
                            }).catch(err => {
                                console.log(err)
                            })
                    }
                }
            }
        } else {
            console.log('请先选择文件')
        }
    }

    const getUploadButton = () => {
    if(uploading) {
        return <Button type='primary' disabled onClick={uploadHandle}>上传中...</Button>
    } else {
        return <Button type='primary' onClick={uploadHandle}>上传</Button>
    }
    }
    return (
        <div className="content-all">
            <Dragger {...props}>
                <p className="ant-upload-drag-icon">
                <InboxOutlined />
                </p>
                <p className="ant-upload-text">文件拖拽至此或点击上传</p>
                <p className="ant-upload-hint">
                支持单个或批量上传
                </p>
            </Dragger>
            {
                getUploadButton()
            }
        </div>
    )
}

export default UploadSerior;
